﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;


namespace SkinableFormsLib
{
	public class LWLabel : Label, ILWControl
	{
		SolidBrush _fontBrush = new SolidBrush(Color.Black);
		SolidBrush _backBrush = new SolidBrush(Color.Black);
		Graphics _graphics;
		Bitmap _lwBitmap;
		internal Rectangle _lwRectangle;
		internal GraphicsPath _stringPath;
		internal GraphicsPath _stringShadowPath;

		internal byte _lwOpacity = 255;
		public byte LWOpacity
		{
			get { return _lwOpacity; }
			set
			{
				_lwOpacity = value;
				_shadowBrush = new SolidBrush(Color.FromArgb(255, _lwShadowColor));
				_fontBrush = new SolidBrush(Color.FromArgb(_lwOpacity, ForeColor));
			}
		}



		#region ILWControl Members

		internal bool _lwDragForm = false;
		public bool LWDragForm
		{
			get
			{
				return _lwDragForm;
			}
			set
			{
				_lwDragForm = value;
			}
		}


		Bitmap SkinableFormsLib.ILWControl.LWBitmap
		{
			get
			{
				return _lwBitmap;
			}
		}

		#endregion

		protected override void OnPaintBackground(PaintEventArgs pevent)
		{
			if (DesignMode)
			{
				base.OnPaintBackground(pevent);
			}
		}
		
		internal bool _hasShadow = false;
		internal Point _lwShadowShift;
		public Point LWShadowShift
		{
			get
			{
				return _lwShadowShift;
			}
			set
			{
				_lwShadowShift = value;
				if (!_lwShadowShift.IsEmpty && _lwShadowColor != Color.Transparent)
				{
					_hasShadow = true;
					InitStringShadowPath();
				}
				else
				{
					_hasShadow = false;
				}


			}
		}
		internal SolidBrush _shadowBrush = (SolidBrush)Brushes.Black;
		private Color _lwShadowColor = Color.Transparent;
		public Color LWShadowColor
		{
			get
			{
				return _lwShadowColor;
			}
			set
			{
				_lwShadowColor = value;
				_shadowBrush = new SolidBrush(Color.FromArgb(_lwOpacity, _lwShadowColor));

				if (!_lwShadowShift.IsEmpty && _lwShadowColor != Color.Transparent)
				{
					_hasShadow = true;
					InitStringShadowPath();
				}
				else
				{
					_hasShadow = false;
				}
			}
		}


		protected override void OnPaint(PaintEventArgs e)
		{

			if (DesignMode)
			{
				//base.OnPaint(e);
				//return;
				//_graphics = e.Graphics;
			}



			if (_lwBitmap == null)
			{
				_lwBitmap = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			}
			if (_graphics == null)
			{
				_graphics = Graphics.FromImage(_lwBitmap);
				_graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
				_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
				_graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
				_graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
				_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

			}
			_graphics.Clear(Color.Transparent);
			if (!_lwTransparent)
			{
				_graphics.FillRectangle(_backBrush, _lwRectangle);


			}

			if (_hasShadow)
			{
				//TODO AddBackgroundImage BLUR functionality
				//  _graphics.DrawString(Text, Font, _shadowBrush, _lwShadowShift.X, _lwShadowShift.Y, StringFormat.GenericDefault);
				PaintText(_graphics, _shadowBrush, _stringShadowPath);
				//_graphics.FillPath(_shadowBrush, _stringShadowPath);
			}






			//e.Graphics.GetHdc()

			//_graphics.DrawString(Text, Font, _fontBrush, 0, 0, StringFormat.GenericTypographic);
			PaintText(_graphics, _fontBrush, _stringPath);
			//PaintText(e.Graphics, e.ClipRectangle);
			//_graphics.FillPath(_fontBrush, _stringPath);

			if (DesignMode)
			{
				e.Graphics.DrawImage(_lwBitmap, 0, 0);
				//base.OnPaint(e);
			}
		}

		internal void PaintText(Graphics g, Brush b, GraphicsPath gp)
		{

			g.FillPath(b, gp);
		}

		public override string Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				base.Text = value;

				InitStringPath();
				InitStringShadowPath();
			}
		}

		internal virtual void InitStringPath()
		{
			_stringPath = new GraphicsPath();
			_stringPath.AddString(this.Text, Font.FontFamily, (int)Font.Style, Font.Size * 4 / 3, Point.Empty, StringFormat.GenericDefault);
			_stringPath.Flatten();


		}

		internal virtual void InitStringShadowPath()
		{
			_stringShadowPath = new GraphicsPath();
			_stringShadowPath.AddString(this.Text, Font.FontFamily, (int)Font.Style, Font.Size * 4 / 3, _lwShadowShift, StringFormat.GenericDefault);
			_stringShadowPath.Flatten();

		}



		protected override void Dispose(bool disposing)
		{
			if (_graphics != null)
				_graphics.Dispose();
			if (_lwBitmap != null)
				_lwBitmap.Dispose();
			if (_fontBrush != null)
				_fontBrush.Dispose();
			base.Dispose(disposing);

		}
		public override Color ForeColor
		{
			get
			{
				return base.ForeColor;
			}
			set
			{
				base.ForeColor = value;
				_fontBrush = new SolidBrush(Color.FromArgb(_lwOpacity, ForeColor));

			}
		}

		public override Color BackColor
		{
			get
			{
				return base.BackColor;
			}
			set
			{
				base.BackColor = value;
				_backBrush = new SolidBrush(BackColor);

			}
		}

		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
			_lwRectangle.Width = Width;
			_lwRectangle.Height = Height;
		}





		#region ILWControl Members

		private bool _lwTransparent = true;
		public bool LWTransparent
		{
			get
			{
				return _lwTransparent;
			}
			set
			{
				_lwTransparent = value;
			}
		}

		#endregion

		#region ILWControl Members


		public Color LWTransparentColor
		{
			get
			{
				return Color.Transparent;
			}
			set
			{

			}
		}

		public bool LWTransparency
		{
			get
			{
				return true;
			}
		}




		public Color LWDesiredBackColor
		{
			get
			{
				return Color.Transparent;
			}
			set
			{

			}
		}

		#endregion


		protected override void WndProc(ref Message m)
		{
			if (m.Msg == Win32.WM_PAINT)
				OnPaint(null);
			base.WndProc(ref m);
		}

	}
}
